#include <stdint.h>
#include <functional>
#include <unordered_map>
#include <vector>
#include <memory>
#include <iostream>
#include <unistd.h>

using TaskFunction = std::function<void()>;
using ReleaseFunction = std::function<void()>;
class TaskTimer
{
private:
    uint64_t _id;
    uint32_t _timeout;
    TaskFunction _task_cb;
    ReleaseFunction _release_cb;
    bool _cancle; //默认为false 表示没有被取消
public:
    TaskTimer(uint64_t id, uint32_t timeout, TaskFunction task_cb) : _id(id), _timeout(timeout), _task_cb(task_cb),_cancle(false)
    {
    }
    void SetRelease(const ReleaseFunction &cb)
    {
        _release_cb = cb;
    }
    void Cancle() {_cancle=true;}
    uint32_t DelayTime() { return _timeout; }
    ~TaskTimer()
    { // 时间轮通过释放智能指针，来执行析构函数，进行任务处理以及资源释放
        if (!_cancle) _task_cb();
        _release_cb();
    }
};
using PtrTimer = std::shared_ptr<TaskTimer>;
using WeakPtr = std::weak_ptr<TaskTimer>;
class TimerWheel
{
private:
    // C++类中初始化的顺序是我们定义的顺序
    int _capacity; // 时间轮的尺度 (大小)
    int _tick;     // 指针指向哪，就说明这个位置超时了，就要进行处理
    std::vector<std::vector<PtrTimer>> _wheel;
    std::unordered_map<uint64_t, WeakPtr> _timers;

public:
    TimerWheel() : _capacity(60), _tick(0), _wheel(_capacity)
    {
    }
    void TimerAdd(uint64_t id, uint32_t delay, TaskFunction task_cb)
    {
        PtrTimer pt(new TaskTimer(id, delay, task_cb));
        pt->SetRelease(std::bind(&TimerWheel::Release, this, id));
        auto pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _timers[id] = pt; // 使用weak_ptr保存起来
    }
    void TimerCancle(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return;
        }
        //如果已经失效了，lock会返回一个空的shared_ptr
        PtrTimer pt = it->second.lock(); 
        if (pt) pt->Cancle(); 
    }
    void TimerRefresh(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return;
        }
        PtrTimer pt = it->second.lock();
        // PtrTimer pt(it->second); // shared_ptr可以直接使用weak_ptr构造
        uint32_t delay = pt->DelayTime();
        // 从当前的指针开始延迟 delay 秒 再超时处理。没有问题奥。
        auto pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void RunTimer()
    {
        _tick = (_tick + 1) % _capacity;
        // 把所有的数据清除，如果智能指针的引用计数减为0，就执行析构函数.
        _wheel[_tick].clear(); 
    }
    ~TimerWheel() {}
private:
    void Release(uint64_t id)
    { //
        auto it = _timers.find(id);
        if (it != _timers.end())
        {
            _timers.erase(it);
        }
    }
};

void Func(uint64_t id)
{
    printf("我是%ld号任务, 我超时了!!\n", id);
}

class Test
{
public:
    Test(){std::cout << "构造\n";}
    ~Test(){std::cout << "析构\n";}
};
void Del(Test*t){
    delete t;
}
int main()
{
    TimerWheel wheel;
    Test* t = new Test();
    wheel.TimerAdd(888,5,std::bind(Del,t));
    for (int i = 0; i < 5; i++){
        sleep(1);
        std::cout << "刷新一次，再过5秒销毁\n";
        wheel.TimerRefresh(888);
        wheel.RunTimer();
    }
    // wheel.TimerCancle(888);
    int cnt = 6;
    while(cnt--){
        std::cout << "------------------------\n";
        sleep(1);
        wheel.RunTimer();
    }

    // int number = 1;
    // TimerWheel wheel;
    // wheel.TimerAdd(number, 3, std::bind(Func, number));
    // number++;
    // wheel.TimerAdd(number, 3, std::bind(Func, number++));
    // int cnt = 1;
    // while (1)
    // {
    //     wheel.TimerRefresh(1);
    //     sleep(1);
    //     wheel.RunTimer();
    // }
    // 此时我就要看到，2号任务3秒之后超时，1号任务一直不超时。
    return 0;
}